import { spawn } from 'child_process';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';

/**
 * 获取当前项目路径
 */
export function getProjectPath() {
    return process.cwd();
}

/**
 * 修剪输入的path
 */
export function trimPath(dir: string) {
    if (typeof dir !== 'string') return '';

    dir = dir.trim();
    if (!dir) return '';

    if (dir[0] === '\'' || dir[0] === '"') {
        dir = dir.slice(1, dir.length - 1);
    }
    return dir;
}

/**
 * 文件夹是否存在
 */
export function isDirectoryExists(dir: string) {
    return fs.existsSync(dir);
}

/**
 * 文件夹是否存在并为空
 */
export function isDirectoryEmpty(dir: string) {
    return fs.existsSync(dir) && fs.readdirSync(dir).filter(filename => filename[0] !== '.').length === 0;
}

/**
 * 创建目录
 */
export function createDirectory(dir: string) {
    if (fs.existsSync(dir) == false) {
        fs.mkdirSync(dir);
    }
}

/**
 * 递归遍历文件夹内所有子孙文件(及文件夹)
 */
export function searchFiles(dir: string, callback: (item_path: string, isDirectory: boolean) => void | false) {
    if (fs.existsSync(dir) !== true) return;

    let files = fs.readdirSync(dir);
    files.forEach(function (item) {
        let item_path = path.join(dir, item);
        if (fs.statSync(item_path).isDirectory()) {
            if (callback(item_path, true) === false) return;
            searchFiles(item_path, callback);
        }
        else {
            if (callback(item_path, false) === false) return;
        }
    });
}

/**
 * 遍历「当前」文件夹内所有的文件(及文件夹)
 */
export function eachFiles(dir: string, callback: (item_path: string, isDirectory: boolean) => void | false) {
    if (fs.existsSync(dir) !== true) return;

    let files = fs.readdirSync(dir);
    files.forEach(function (item) {
        let item_path = path.join(dir, item);
        let result = callback(item_path, fs.statSync(item_path).isDirectory());
        if (result === false) return;
    });
}

/**
 * 删除目录及包含的文件
 * @param dir 
 * @param onlyInner 只删除内部保留当前空文件夹
 */
export function deleteDirectory(dir: string, onlyInner: boolean = false) {
    if (fs.existsSync(dir) == true) {
        let files = fs.readdirSync(dir);
        files.forEach(function (item) {
            let item_path = path.join(dir, item);
            let temp = fs.statSync(item_path);
            if (temp.isDirectory() && !temp.isSymbolicLink()) {
                if (!onlyInner) deleteDirectory(item_path);
            }
            else {
                fs.unlinkSync(item_path);
            }
        });
        if (!onlyInner) fs.rmdirSync(dir);
    }
}

/**
 * 拷贝源目录下的文件到目标目录下(过滤掉所有.git文件或目录)
 * @param src  源
 * @param dest 目标
 */
export function copyDirectory(src: string, dest: string) {
    if (fs.existsSync(src) == false) {
        return false;
    }

    if (fs.existsSync(dest) == false) {
        fs.mkdirSync(dest);
    }

    // 拷贝新的内容进去
    let dirs = fs.readdirSync(src);
    dirs.forEach(function (item) {
        if (item === '.git') return;
        if (item === '.package-lock.json') return;
        let item_path = path.join(src, item);
        let temp = fs.statSync(item_path);
        if (temp.isFile() || temp.isSymbolicLink()) { // 是文件
            fs.copyFileSync(item_path, path.join(dest, item));
        } else if (temp.isDirectory()) { // 是目录
            copyDirectory(item_path, path.join(dest, item));
        }
    });
}

/**
 * 执行cmd指令
 */
export async function executeCmd(cmd: string, args: string[]/**,options?: SpawnOptionsWithoutStdio */) {
    return new Promise(function (resolve, reject) {
        let result = spawn(cmd, args, { shell: true });
        result.on('close', function (code) {
            resolve(code);
        });
        result.stdout.on('data', function (data) {
            console.log('[log]: ' + data);
        });
        result.stderr.on('error', function (data) {
            console.log('[err]: ' + data);
        });
    });
}

/**
 * 获取项目cliconfig.json数据
 * @param dir 项目路径
 */
export function getCliConfigData(dir: string): { type: 'Creator3D' | 'Creator', version: string } {
    const configPath = path.join(dir, 'cliconfig.json');
    if (!fs.existsSync(configPath)) return null;
    const jsonStr = fs.readFileSync(configPath, 'utf-8');
    return JSON.parse(jsonStr);
}

/**
 * 获取项目project.json数据
 * @param dir 项目路径
 */
export function getProjectVersion(dir: string) {
    const projectPath = path.join(dir, 'package.json');
    if (!fs.existsSync(projectPath)) return '';
    const jsonStr = fs.readFileSync(projectPath, 'utf-8');
    const projectData = JSON.parse(jsonStr);
    return projectData.creator?.version || projectData.version || '';
}

/**
 * 获取项目对应的版本的编辑器路径
 * @param dir 项目路径
 */
export function getCocosCmd(dir: string) {
    // 项目配置
    const projectVersion = getProjectVersion(dir);
    if (!projectVersion) return '';

    // 获取Cocos编辑器配置
    const text = fs.readFileSync(path.join(os.homedir(), '/.Cocos/profiles/editor.json'), 'utf-8');
    if (!text) return '';

    const json = JSON.parse(text);

    // 获取编辑器路径
    for (const editor in json['editor']) {
        const creators = json['editor'][editor];
        for (const creator of creators) {
            if (creator.version === projectVersion) {
                return path.join(creator.file, '/Contents/MacOS/CocosCreator');
            }
        }
    }

    return '';
}

/**
 * 对比版本号
 */
export function compareVersion(version1: string, operation: '<' | '<=' | '>' | '>=' | '==', version2: string) {
    const v1 = version1.split('.');
    const v2 = version2.split('.');
    const len = Math.max(v1.length, v2.length);

    while (v1.length < len) {
        v1.push('0');
    }
    while (v2.length < len) {
        v2.push('0');
    }

    for (let i = 0; i < len; i++) {
        const num1 = parseInt(v1[i].match(/[0-9]+/)?.[0] || '0');
        const num2 = parseInt(v2[i].match(/[0-9]+/)?.[0] || '0');

        if (num1 > num2) {
            return operation === '>' || operation === '>=';
        } else if (num1 < num2) {
            return operation === '<' || operation === '<=';
        }
    }

    return operation === '==' || operation === '>=' || operation === '<=';
}